package myJs.myPkg.topology

import myJs.Implicits.{JDJAn, JDS, MyLine, MyPen}
import myJs.myPkg.jquery._

import scala.scalajs.js
import scala.scalajs.js.annotation.{JSGlobal, JSImport, JSName}
import scala.scalajs.js.annotation.JSImport.Namespace
import java.lang.{Boolean => JBoolean, Double => JDouble, Integer => JInt}
import myJs.myPkg.jsext.{JSOptionBuilder, OptMap, noOpts}
import myJs.myPkg.topology.AnchorMode.AnchorMode
import slinky.readwrite.ObjectOrWritten

import scala.scalajs.js.{JSON, |}

/**
 * Created by yz on 19/11/2020
 */

@js.native
@JSGlobal("Le5leTopology.Topology")
class Topology(parent: String, options: TopologyOptions) extends js.Object {

  def open(json: JDJAn): Unit = js.native

  def addNode(node: TopologyNode, focus: Boolean = false): Unit = js.native

  def addLine(line: Line, focus: Boolean = false): Unit = js.native

  def combine(pens: js.Array[Pen], stand: Boolean = false): Unit = js.native

  def toComponent(pens: js.Array[Pen]): TopologyNode = js.native

  def render(): Unit = js.native

  def lock(lock: Lock): Unit = js.native

  def lockPens(pens: js.Array[Pen], lock: Lock): Unit = js.native

  def delete(): Unit = js.native
  def delete(param:String): Unit = js.native
  def delete(param:ObjectOrWritten[List[Pen]]): Unit = js.native

  def updateProps(cache: Boolean = true, pens: js.Array[Pen]): Unit = js.native

  def on(events: String, handler: js.Function1[MyPen, Any]): JQuery = js.native

  def on(events: String, handler: js.Function0[Any]): JQuery = js.native
  @JSName("on")
  def copyOn(events: String, handler: js.Function1[TopologyData,Any]): JQuery = js.native

  def find(id: String): MyPen = js.native

  @JSName("find")
  def findOp(id: String): js.UndefOr[MyPen] = js.native

  val data: TopologyData = js.native

  var hoverLayer: HoverLayer = js.native

  var activeLayer: ActiveLayer = js.native

}

object Topology {

  def apply(parent: String = null, options: TopologyOptions = null) = {
    new Topology(parent, options)
  }

}

object TopologyOptions extends TopologyOptionsBuilder(noOpts) {

  def apply(hideRotateCP: Boolean, hideSizeCP: Boolean, hideAnchor: JBoolean = null, disableScale: Boolean,
            disableEmptyLine: Boolean, autoAnchor: Boolean, alwaysAnchor: JBoolean = null, rotateCursor: String = null,
            hoverCursor: String = null, disableDockLine: JBoolean = null, hideInput: JBoolean = null, anchorFillStyle: String = null) = {
    TopologyOptions.hideRotateCP(hideRotateCP).hideSizeCP(hideSizeCP).hideAnchor(hideAnchor).disableScale(disableScale).
      disableEmptyLine(disableEmptyLine).autoAnchor(autoAnchor).alwaysAnchor(alwaysAnchor).rotateCursor(rotateCursor).
      hoverCursor(hoverCursor).disableDockLine(disableDockLine).hideInput(hideInput).anchorFillStyle(anchorFillStyle)
  }

}

class TopologyOptionsBuilder(val dict: OptMap) extends JSOptionBuilder[TopologyOptions, TopologyOptionsBuilder](new TopologyOptionsBuilder(_)) {

  def hideRotateCP(v: Boolean) = jsOpt("hideRotateCP", v)

  def hideSizeCP(v: Boolean) = jsOpt("hideSizeCP", v)

  def hideAnchor(v: Boolean) = jsOpt("hideAnchor", v)

  def disableScale(v: Boolean) = jsOpt("disableScale", v)

  def disableEmptyLine(v: Boolean) = jsOpt("disableEmptyLine", v)

  def autoAnchor(v: Boolean) = jsOpt("autoAnchor", v)

  def alwaysAnchor(v: Boolean) = jsOpt("alwaysAnchor", v)

  def rotateCursor(v: String) = jsOpt("rotateCursor", v)

  def hoverCursor(v: String) = jsOpt("hoverCursor", v)

  def disableDockLine(v: Boolean) = jsOpt("disableDockLine", v)

  def hideInput(v: Boolean) = jsOpt("hideInput", v)

  def anchorFillStyle(v: String) = jsOpt("anchorFillStyle", v)

}

trait TopologyOptions extends js.Object {

}

@js.native
trait Lock extends js.Any

object Lock {

  val None = 0.asInstanceOf[Lock]

  val Readonly = 1.asInstanceOf[Lock]

  val NoMove = 2.asInstanceOf[Lock]

  val NoEvent = 10.asInstanceOf[Lock]

}

@js.native
@JSGlobal("Le5leTopology.TopologyData")
class TopologyData extends js.Object {

  val pens: js.Array[Pen] = js.native

  var locked: Lock = js.native

}

@js.native
trait AnchorType extends js.Any

object AnchorType {

  val OnlyBottom = 0.asInstanceOf[AnchorType]

  val UpAndBottom = 1.asInstanceOf[AnchorType]

  val OnlyUp = 2.asInstanceOf[AnchorType]

  val None = 3.asInstanceOf[AnchorType]

}

@js.native
@JSGlobal("Le5leTopology.Node")
class TopologyNode(options: TopologyNodeOptions) extends Pen {

  var name: String = js.native

  var borderRadius: Double = js.native

  var paddingBottom: Double = js.native

  var paddingTop: Double = js.native

  var paddingLeft: Double = js.native

  var paddingRight: Double = js.native

  var text: String = js.native

  var rect: Rect = js.native

  var textRect: Rect = js.native

  var fullTextRect: Rect = js.native

  var anchors: js.Array[Point] = js.native

  var rotatedAnchors: js.Array[Point] = js.native

  var hideSizeCP: Boolean = js.native

}

object TopologyNode {

  def apply(name: String, borderRadius: Double, paddingBottom: Double, paddingTop: Double, paddingLeft: Double,
            paddingRight: Double, text: String, rect: Rect, textRect: Rect = null, fullTextRect: Rect = null,
            id: String = null, anchors: js.Array[Point] = null, rotatedAnchors: js.Array[Point] = null,
            hideSizeCP: JBoolean = null, anchorType: AnchorType = AnchorType.OnlyBottom, hideAnchor: JBoolean = null) = {
    val options = TopologyNodeOptions.name(name).borderRadius(borderRadius).paddingBottom(paddingBottom).
      paddingTop(paddingTop).paddingLeft(paddingLeft).paddingRight(paddingRight).text(text).rect(rect).id(id).
      anchors(anchors).hideSizeCP(hideSizeCP).anchorType(anchorType).hideAnchor(hideAnchor)
    val topology = new TopologyNode(options)
    topology
  }

}

object TopologyNodeOptions extends TopologyNodeOptionsBuilder(noOpts)

class TopologyNodeOptionsBuilder(val dict: OptMap) extends JSOptionBuilder[TopologyNodeOptions, TopologyNodeOptionsBuilder](new TopologyNodeOptionsBuilder(_)) {

  def name(v: String) = jsOpt("name", v)

  def borderRadius(v: Double) = jsOpt("borderRadius", v)

  def paddingBottom(v: Double) = jsOpt("paddingBottom", v)

  def paddingTop(v: Double) = jsOpt("paddingTop", v)

  def paddingLeft(v: Double) = jsOpt("paddingLeft", v)

  def paddingRight(v: Double) = jsOpt("paddingRight", v)

  def text(v: String) = jsOpt("text", v)

  def rect(v: Rect) = jsOpt("rect", v)

  def id(v: String) = jsOpt("id", v)

  def anchors(v: js.Array[Point]) = jsOpt("anchors", v)

  def hideSizeCP(v: Boolean) = jsOpt("hideSizeCP", v)

  def hideAnchor(v: Boolean) = jsOpt("hideAnchor", v)

  def anchorType(v: AnchorType) = {
    jsOpt("anchorType", v)
  }

}

trait TopologyNodeOptions extends js.Object {

}

@js.native
@JSGlobal("Le5leTopology.Rect")
class Rect extends js.Object {

  var x: JDouble = js.native

  var y: Double = js.native

  var width: Double = js.native

  var height: Double = js.native

  var center: Point = js.native

  var ex: Double = js.native

  var ey: Double = js.native

}

object Rect {

  def apply(x: JDouble = null, y: JDouble = null, width: JDouble = null, height: JDouble = null, center: Point = null,
            ex: JDouble = null, ey: JDouble = null) = {
    val rect = new Rect
    rect.x = x
    rect.y = y
    rect.width = width
    rect.height = height
    rect.center = center
    rect.ex = ex
    rect.ey = ey
    rect
  }

}

@js.native
@JSGlobal("Le5leTopology.Point")
class Point extends js.Object {

  var x: JDouble = js.native

  var y: JDouble = js.native

  var direction: Direction = js.native

  var id: String = js.native

  var mode: AnchorMode = js.native

  var anchorIndex: Int = js.native

  var autoAnchor: Boolean = js.native

}

object AnchorMode extends Enumeration {

  type AnchorMode = Value

  val Default, In, Out = Value

}

object Point {

  def apply(x: JDouble = null, y: JDouble = null, direction: Direction = null, mode: AnchorMode = null,
            anchorIndex: JInt = null, id: String = null, autoAnchor: JBoolean = null) = {
    val point = new Point
    point.x = x
    point.y = y
    point.direction = direction
    point.mode = mode
    point.anchorIndex = anchorIndex
    point.id = id
    point.autoAnchor = autoAnchor
    point
  }

}

@js.native
trait Direction extends js.Any

object Direction {

  val None = 0.asInstanceOf[Direction]

  val Up = 1.asInstanceOf[Direction]

  val Right = 2.asInstanceOf[Direction]

  val Bottom = 3.asInstanceOf[Direction]

  val Left = 4.asInstanceOf[Direction]

}

@js.native
trait PenType extends js.Any

object PenType {

  val Node = 0.asInstanceOf[PenType]

  val Line = 1.asInstanceOf[PenType]

}

@js.native
@JSGlobal("Le5leTopology.Pen")
class Pen extends js.Object {

  var id: String = js.native

  var `type`: PenType = js.native

  var strokeStyle: String = js.native

  var locked: Lock = js.native

  var hoverCursor: String = js.native

}

object Pen {

  def apply(x: JDouble = null, y: JDouble = null, direction: Direction = null) = {
    val rect = new Point
    rect.x = x
    rect.y = y
    rect.direction = direction
    rect
  }

}

@js.native
@JSGlobal("Le5leTopology.Line")
class Line(options: LineOptions) extends Pen {

  var to: Point = js.native

  var from: Point = js.native

  var controlPoints: js.Array[Point] = js.native

  var name: String = js.native

}

object Line {

  def apply(from: Point, to: Point, name: String, controlPoints: js.Array[Point], toArrow: String, locked: Lock) = {
    val options = LineOptions.from(from).to(to).name(name).controlPoints(controlPoints).toArrow(toArrow).locked(locked)
    new Line(options)
  }

}

object LineOptions extends LineOptionsBuilder(noOpts)

class LineOptionsBuilder(val dict: OptMap) extends JSOptionBuilder[LineOptions, LineOptionsBuilder](new LineOptionsBuilder(_)) {

  def from(v: Point) = jsOpt("from", v)

  def to(v: Point) = jsOpt("to", v)

  def name(v: String) = jsOpt("name", v)

  def controlPoints(v: js.Array[Point]) = jsOpt("controlPoints", v)

  def toArrow(v: String) = jsOpt("toArrow", v)

  def locked(v: Lock) = jsOpt("locked", v)

}

trait LineOptions extends js.Object {

}

@js.native
@JSGlobal("Le5leTopology.HoverLayer")
class HoverLayer(options: TopologyOptions, tId: String) extends js.Object {

  var to: Point = js.native

  var from: Point = js.native

  var controlPoints: js.Array[Point] = js.native

  var name: String = js.native

}

object HoverLayer {

  def apply(x: JDouble = null, y: JDouble = null, direction: JDouble = null) = {
    val layer = new HoverLayer(TopologyOptions, "123")
    layer
  }

}

@js.native
@JSGlobal("Le5leTopology.ActiveLayer")
class ActiveLayer(options: TopologyOptions, tId: String) extends js.Object {

  val nodes: js.Array[TopologyNode] = js.native

  def add(pen: Pen): Unit = js.native

  def setPens(pens: js.Array[Pen]): Unit = js.native

  def clear(): Unit = js.native


}
